package com.ideal.frame.node.netty.server;

import com.ideal.frame.node.entity.NodeTb;
import com.ideal.frame.node.netty.NettyMsg;
import com.ideal.frame.node.service.NodeService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;

/**
 * Created by haoxy on 2018/10/17.
 * E-mail:hxyHelloWorld@163.com
 * github:https://github.com/haoxiaoyong1014
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class NettyServerHandle extends SimpleChannelInboundHandler<NettyMsg> {

    private int retryTimes = 0;
    private final int MAX_RETRY_TIMES = 3;

    // 心跳返回客户端的信息
    private ByteBuf HEART_BEAT = null;

    @Autowired
    NodeService nodeService;

    @PostConstruct
    public void init(){
        NodeTb node = nodeService.getByLevel();
        HEART_BEAT = Unpooled.unreleasableBuffer(
                Unpooled.copiedBuffer(new NettyMsg(node.getId(), node.getNodename(), "pong").toString(), CharsetUtil.UTF_8));
    }


    /**
     * 取消绑定
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        SocketChannel channel = (SocketChannel) ctx.channel();
        String host = channel.remoteAddress().getHostName();
        int port = channel.remoteAddress().getPort();
        String nowTimeString = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        log.error("与客户端[{}:{}]断开连接,断开的时间为：{}", host, port, nowTimeString);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if (idleStateEvent.state() == IdleState.READER_IDLE) {
                log.warn("已经{}秒未读到消息", 5);
//              ctx.writeAndFlush(HEART_BEAT).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);

//                // 失败计数器次数大于等于3次的时候，关闭链接，等待client重连
//                if(this.retryTimes > this.MAX_RETRY_TIMES){
////                    log.warn("===>服务端===(读超时，关闭chanel)");
////                    log.info("连续超过{}次未收到client的ping消息，那么关闭该通道，等待client重连", this.MAX_RETRY_TIMES);
////                    ctx.close();
////                    this.retryTimes = 0;
//                } else {
//                    // 失败计数器加1
//                    this.retryTimes++;
//                }
            }
        }
        super.userEventTriggered(ctx, evt);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, NettyMsg nettyMsg) throws Exception {
        SocketChannel channel = (SocketChannel) ctx.channel();
        String host = channel.remoteAddress().getHostName();
        int port = channel.remoteAddress().getPort();
        log.info("服务端收到[{}:{}]消息，nettyMsg={}", host, port, nettyMsg);
        //我们调用writeAndFlush（Object）来逐字写入接收到的消息并刷新线路
        ctx.writeAndFlush(HEART_BEAT);
    }
}
